package com.kyivmohyla.kma2.client.presenter.engineer;

import com.google.gwt.cell.client.NumberCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.DatePicker;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.kyivmohyla.kma2.client.UserService;
import com.kyivmohyla.kma2.client.events.OrderExportEvent;
import com.kyivmohyla.kma2.client.events.engineer.EngineerEditOrderEvent;
import com.kyivmohyla.kma2.client.gin.Injector;
import com.kyivmohyla.kma2.client.presenter.Presenter;
import com.kyivmohyla.kma2.client.utils.Dialog;
import com.kyivmohyla.kma2.client.utils.ExportOrder;
import com.kyivmohyla.kma2.client.view.common.OrderCellTableWidget;
import com.kyivmohyla.kma2.shared.model.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class EngineerMainViewPresenter implements Presenter {

    private final static DateTimeFormat dateFormat = DateTimeFormat.getFormat("dd.MM.yyyy");
    private final static DateTimeFormat dateTimeFormat = DateTimeFormat.getFormat("dd.MM.yyyy HH:mm");
    private final Display display;
    private final Injector injector = Injector.INSTANCE;
    private UIStaff engineer;
    private UIOrder selectedOrder;
    private CellTable<UIOrder> orderCellTable;
    private SingleSelectionModel<UIOrder> selectionModel;
    private List<ExportOrder> exportOrders;

    public EngineerMainViewPresenter(UIStaff engineer) {
        this.display = injector.getEngineerMainView();
        this.engineer = engineer;
        this.orderCellTable = (CellTable) this.display.getOrderCellTable().getOrderCellTable();
        createTableStructure();
        bind();

        String formattedDate = dateFormat.format(new Date());
        UserService.App.getInstance().getOrdersByStateAndDateAndPosition(new int[]{3}, formattedDate, this.engineer.getStaffId(), new AsyncCallback<List<UIOrder>>() {
            @Override
            public void onFailure(Throwable throwable) {
                Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
            }

            @Override
            public void onSuccess(List<UIOrder> result) {
                ListDataProvider<UIOrder> dataProvider = new ListDataProvider<UIOrder>(result);
                dataProvider.addDataDisplay(display.getOrderCellTable().getOrderCellTable());
                exportOrders = new ArrayList<ExportOrder>();
                for (final UIOrder order : result) {
                    final ExportOrder exportOrder = new ExportOrder();
                    exportOrder.setOrderId(order.getOrderId());
                    exportOrder.setCreateDate(order.getCreateDate());
                    exportOrder.setStartDate(order.getStartDate());
                    exportOrder.setEndDate(order.getEndDate());
                    exportOrder.setCommentary(order.getCommentary());
                    exportOrder.setStateName(order.getStateName());
                    UserService.App.getInstance().getCustomerById(order.getCustomerId(), new AsyncCallback<UICustomer>() {
                        @Override
                        public void onFailure(Throwable throwable) {
                            Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                        }

                        @Override
                        public void onSuccess(UICustomer result) {
                            exportOrder.setCustomerName(result.getFirstName() + " " + result.getLastName());
                            exportOrder.setCustomerAddress(result.getAddress());
                            exportOrder.setCustomerEmail(result.getEmail());
                            exportOrder.setCustomerPhone(result.getPhone());
                        }
                    });
                    UserService.App.getInstance().getServiceByOrderId(order.getOrderId(), new AsyncCallback<List<UIService>>() {
                        @Override
                        public void onFailure(Throwable throwable) {
                            Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                        }

                        @Override
                        public void onSuccess(List<UIService> result) {
                            exportOrder.setServices(result);
                            UserService.App.getInstance().getEquipmentByServicesList(result, new AsyncCallback<List<UIEquipment>>() {
                                @Override
                                public void onFailure(Throwable throwable) {
                                    Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                                }

                                @Override
                                public void onSuccess(List<UIEquipment> uiEquipments) {
                                    exportOrder.setEquipments(uiEquipments);
                                    UserService.App.getInstance().getEquipmentByOrderId(order.getOrderId(), new AsyncCallback<List<UIEquipment>>() {
                                        @Override
                                        public void onFailure(Throwable throwable) {
                                            Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                                        }

                                        @Override
                                        public void onSuccess(List<UIEquipment> uiEquipments) {
                                            exportOrder.getEquipments().addAll(uiEquipments);
                                        }
                                    });
                                }
                            });
                        }
                    });
                    exportOrders.add(exportOrder);
                }
            }
        });
    }

    public EngineerMainViewPresenter(UIStaff engineer, Date date) {
        this.display = injector.getEngineerMainView();
        this.engineer = engineer;
        this.orderCellTable = (CellTable) this.display.getOrderCellTable().getOrderCellTable();
        createTableStructure();
        bind();
        String formattedDate = dateFormat.format(date);
        ((DatePicker) this.display.getDatePicker()).setValue(date, false);
        UserService.App.getInstance().getOrdersByStateAndDateAndPosition(new int[]{3}, formattedDate, this.engineer.getStaffId(), new AsyncCallback<List<UIOrder>>() {
            @Override
            public void onFailure(Throwable throwable) {
                Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
            }

            @Override
            public void onSuccess(List<UIOrder> result) {
                ListDataProvider<UIOrder> dataProvider = new ListDataProvider<UIOrder>(result);
                dataProvider.addDataDisplay(display.getOrderCellTable().getOrderCellTable());
                exportOrders = new ArrayList<ExportOrder>();
                for (final UIOrder order : result) {
                    final ExportOrder exportOrder = new ExportOrder();
                    exportOrder.setOrderId(order.getOrderId());
                    exportOrder.setCreateDate(order.getCreateDate());
                    exportOrder.setStartDate(order.getStartDate());
                    exportOrder.setEndDate(order.getEndDate());
                    exportOrder.setCommentary(order.getCommentary());
                    exportOrder.setStateName(order.getStateName());
                    UserService.App.getInstance().getCustomerById(order.getCustomerId(), new AsyncCallback<UICustomer>() {
                        @Override
                        public void onFailure(Throwable throwable) {
                            Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                        }

                        @Override
                        public void onSuccess(UICustomer result) {
                            exportOrder.setCustomerName(result.getFirstName() + " " + result.getLastName());
                            exportOrder.setCustomerAddress(result.getAddress());
                            exportOrder.setCustomerEmail(result.getEmail());
                            exportOrder.setCustomerPhone(result.getPhone());
                        }
                    });
                    UserService.App.getInstance().getServiceByOrderId(order.getOrderId(), new AsyncCallback<List<UIService>>() {
                        @Override
                        public void onFailure(Throwable throwable) {
                            Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                        }

                        @Override
                        public void onSuccess(List<UIService> result) {
                            exportOrder.setServices(result);
                            UserService.App.getInstance().getEquipmentByServicesList(result, new AsyncCallback<List<UIEquipment>>() {
                                @Override
                                public void onFailure(Throwable throwable) {
                                    Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                                }

                                @Override
                                public void onSuccess(List<UIEquipment> uiEquipments) {
                                    exportOrder.setEquipments(uiEquipments);
                                    UserService.App.getInstance().getEquipmentByOrderId(order.getOrderId(), new AsyncCallback<List<UIEquipment>>() {
                                        @Override
                                        public void onFailure(Throwable throwable) {
                                            Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                                        }

                                        @Override
                                        public void onSuccess(List<UIEquipment> uiEquipments) {
                                            exportOrder.getEquipments().addAll(uiEquipments);
                                        }
                                    });
                                }
                            });
                        }
                    });
                    exportOrders.add(exportOrder);
                }
            }
        });
    }

    private void createTableStructure() {
        selectionModel = new SingleSelectionModel<UIOrder>();
        selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
            @Override
            public void onSelectionChange(SelectionChangeEvent selectionChangeEvent) {
                selectedOrder = (UIOrder) ((SingleSelectionModel) selectionChangeEvent.getSource()).getSelectedObject();
            }
        });
        orderCellTable.setSelectionModel(selectionModel);

        orderCellTable.addDomHandler(new DoubleClickHandler() {
            @Override
            public void onDoubleClick(DoubleClickEvent doubleClickEvent) {
                selectedOrder = selectionModel.getSelectedObject();
                if (selectedOrder != null) {
                    injector.getEventBus().fireEvent(new EngineerEditOrderEvent(selectedOrder));
                } else {
                    Dialog.getInstance().createDialogBoxWithMessage("Please,", "Select an Order First.");
                }
            }
        }, DoubleClickEvent.getType());

        orderCellTable.addColumn(new Column<UIOrder, Number>(new NumberCell()) {
            @Override
            public Number getValue(UIOrder object) {
                return object.getOrderId();
            }
        }, "Order ID");
        orderCellTable.addColumn(new Column<UIOrder, String>(new TextCell()) {
            @Override
            public String getValue(UIOrder object) {
                return object.getCustomerName();
            }
        }, "Customer Name");
        orderCellTable.addColumn(new Column<UIOrder, String>(new TextCell()) {
            @Override
            public String getValue(UIOrder object) {
                return object.getCustomerAddress();
            }
        }, "Customer Address");
        orderCellTable.addColumn(new Column<UIOrder, String>(new TextCell()) {
            @Override
            public String getValue(UIOrder object) {
                if (object.getStartDate() != null)
                    return dateTimeFormat.format(object.getStartDate());
                return "Not Planned Yet";
            }
        }, "Start");
        orderCellTable.addColumn(new Column<UIOrder, String>(new TextCell()) {
            @Override
            public String getValue(UIOrder object) {
                if (object.getStartDate() != null)
                    return dateTimeFormat.format(object.getEndDate());
                return "Not Planned Yet";
            }
        }, "End");
    }

    private void bind() {
        this.display.getDatePicker().addValueChangeHandler(new ValueChangeHandler<Date>() {
            @Override
            public void onValueChange(ValueChangeEvent<Date> valueChangeEvent) {
                doValueChange(valueChangeEvent.getValue());
            }
        });
        this.display.getExportOrdersButton().addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                injector.getEventBus().fireEvent(new OrderExportEvent(exportOrders));
            }
        });
    }

    private void doValueChange(Date date) {
        String formattedDate = dateFormat.format(date);
        UserService.App.getInstance().getOrdersByStateAndDateAndPosition(new int[]{3}, formattedDate, this.engineer.getStaffId(), new AsyncCallback<List<UIOrder>>() {
            @Override
            public void onFailure(Throwable throwable) {
                Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
            }

            @Override
            public void onSuccess(List<UIOrder> uiOrders) {
                ListDataProvider<UIOrder> dataProvider = new ListDataProvider<UIOrder>(uiOrders);
                dataProvider.addDataDisplay(display.getOrderCellTable().getOrderCellTable());
                exportOrders = new ArrayList<ExportOrder>();
                for (final UIOrder order : uiOrders) {
                    final ExportOrder exportOrder = new ExportOrder();
                    exportOrder.setOrderId(order.getOrderId());
                    exportOrder.setCreateDate(order.getCreateDate());
                    exportOrder.setStartDate(order.getStartDate());
                    exportOrder.setEndDate(order.getEndDate());
                    exportOrder.setCommentary(order.getCommentary());
                    exportOrder.setStateName(order.getStateName());
                    UserService.App.getInstance().getCustomerById(order.getCustomerId(), new AsyncCallback<UICustomer>() {
                        @Override
                        public void onFailure(Throwable caught) {
                            Dialog.getInstance().createDialogBoxWithMessage("Error", caught.getMessage());
                        }

                        @Override
                        public void onSuccess(UICustomer result) {
                            exportOrder.setCustomerName(result.getFirstName() + " " + result.getLastName());
                            exportOrder.setCustomerAddress(result.getAddress());
                            exportOrder.setCustomerEmail(result.getEmail());
                            exportOrder.setCustomerPhone(result.getPhone());
                        }
                    });
                    UserService.App.getInstance().getServiceByOrderId(order.getOrderId(), new AsyncCallback<List<UIService>>() {
                        @Override
                        public void onFailure(Throwable throwable) {
                            Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                        }

                        @Override
                        public void onSuccess(List<UIService> result) {
                            exportOrder.setServices(result);
                            UserService.App.getInstance().getEquipmentByServicesList(result, new AsyncCallback<List<UIEquipment>>() {
                                @Override
                                public void onFailure(Throwable throwable) {
                                    Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                                }

                                @Override
                                public void onSuccess(List<UIEquipment> uiEquipments) {
                                    exportOrder.setEquipments(uiEquipments);
                                    UserService.App.getInstance().getEquipmentByOrderId(order.getOrderId(), new AsyncCallback<List<UIEquipment>>() {
                                        @Override
                                        public void onFailure(Throwable throwable) {
                                            Dialog.getInstance().createDialogBoxWithMessage("Error", throwable.getMessage());
                                        }

                                        @Override
                                        public void onSuccess(List<UIEquipment> uiEquipments) {
                                            exportOrder.getEquipments().addAll(uiEquipments);
                                        }
                                    });
                                }
                            });
                        }
                    });
                    exportOrders.add(exportOrder);
                }
            }
        });
    }

    @Override
    public void go(HasWidgets container) {
        container.clear();
        container.add(display.asWidget());
    }

    public interface Display {
        HasValueChangeHandlers getDatePicker();

        OrderCellTableWidget getOrderCellTable();

        HasClickHandlers getExportOrdersButton();

        Widget asWidget();
    }
}
